package com.zenith.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenith.common.constant.CommonConstant;
import com.zenith.common.enumcode.RedisEnum;
import com.zenith.common.util.JwtUtil;
import com.zenith.user.mapper.UserMapper;
import com.zenith.user.po.domain.User;
import com.zenith.user.po.dto.LoginDTO;
import com.zenith.user.po.dto.RegisterDTO;
import com.zenith.user.po.vo.LoginVO;
import com.zenith.user.po.vo.UserVO;
import com.zenith.user.service.AnthService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AnthServiceImpl extends ServiceImpl<UserMapper, User> implements AnthService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        try {
            if (loginDTO != null && loginDTO.getUsername() != null && loginDTO.getPassword() != null) {
                User user = baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, loginDTO.getUsername()));
                if (user != null) {
                    if (passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
                        Map<String, Object> claims = new HashMap<>();
                        claims.put(CommonConstant.USER_ID, user.getId());
                        claims.put(CommonConstant.USERNAME, user.getUsername());
                        claims.put(CommonConstant.USER_ROLE, user.getRole());
                        String token = JwtUtil.generateToken(claims);
                        LoginVO loginVO = new LoginVO();
                        loginVO.setToken(token);
                        // 将用户id存储到redis中，并设置过期时间
                        redisTemplate.opsForValue().set(RedisEnum.USER_TOKEN.getKey() + user.getId(), token, 30, TimeUnit.MINUTES);
                        return loginVO;
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("登录失败：用户名或密码错误", e);
        }
        throw new RuntimeException("登录失败：用户名或密码错误");
    }

    @Override
    public void register(RegisterDTO registerDTO) {
        try {
            if (registerDTO != null && registerDTO.getPhone() != null && registerDTO.getPassword() != null) {
                User user = new User();
                log.info("原始密码：{}", registerDTO.getPassword());
                String encode = passwordEncoder.encode(registerDTO.getPassword());
                log.info("加密后的密码：{}", encode);
                user.setPassword(encode);
                user.setRealName(registerDTO.getPhone());
                user.setPhone(registerDTO.getPhone());
                user.setRole(registerDTO.getRole());
                user.setUsername(registerDTO.getPhone());
                user.setAvatar(registerDTO.getAvatar());
                user.setStatus(1);
                user.setIsDelete(0);
                baseMapper.insert(user);
                return;
            }
        } catch (Exception e) {
            throw new RuntimeException("注册失败：", e);
        }
        throw new RuntimeException("注册失败：参数不完整");
    }

    @Override
    public void logout(String token) {
        // 计算token的过期时间
        Claims claims = JwtUtil.parseToken(token);
        Date expiration = claims.getExpiration();
        long ttl = expiration.getTime() - System.currentTimeMillis();

        // 将token添加到撤销列表
        redisTemplate.opsForValue().set(RedisEnum.TOKEN_REVOKED.getKey() + token, "1", ttl, TimeUnit.MILLISECONDS);
    }

    @Override
    public Boolean getUserActive(Long userId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId, userId);
        queryWrapper.eq(User::getIsDelete, 0);
        User user = baseMapper.selectOne(queryWrapper);
        return user != null;
    }

    @Override
    public UserVO getCurrentUser(Long userId) {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId, userId);
        queryWrapper.eq(User::getIsDelete, 0);
        queryWrapper.eq(User::getStatus, 1);
        
        User user = baseMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new RuntimeException("用户不存在或已被禁用");
        }
        
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public LoginVO refreshToken(String token) {
        if (token == null || token.trim().isEmpty()) {
            throw new IllegalArgumentException("Token不能为空");
        }
        
        try {
            // 解析旧Token
            Claims claims = JwtUtil.parseToken(token.replace("Bearer ", ""));
            Long userId = null;
            String username = null;
            String role = null;
            if (claims != null) {
                userId = claims.get(CommonConstant.USER_ID, Long.class);
                username = claims.get(CommonConstant.USERNAME, String.class);
                role = claims.get(CommonConstant.USER_ROLE, String.class);
                log.info("用户ID：{},{},{}", userId , username, role);
            }
            // 验证用户是否仍然有效
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getId, userId);
            queryWrapper.eq(User::getIsDelete, 0);
            queryWrapper.eq(User::getStatus, 1);
            
            User user = baseMapper.selectOne(queryWrapper);
            if (user == null) {
                throw new RuntimeException("用户不存在或已被禁用");
            }
            
            // 生成新Token
            Map<String, Object> newClaims = new HashMap<>();
            newClaims.put(CommonConstant.USER_ID, userId);
            newClaims.put(CommonConstant.USERNAME, username);
            newClaims.put(CommonConstant.USER_ROLE, role);
            
            String newToken = JwtUtil.generateToken(newClaims);
            
            // 将旧Token加入撤销列表
            Claims oldClaims = JwtUtil.parseToken(token.replace("Bearer ", ""));
            Date expiration = oldClaims.getExpiration();
            long ttl = expiration.getTime() - System.currentTimeMillis();
            if (ttl > 0) {
                redisTemplate.opsForValue().set(RedisEnum.TOKEN_REVOKED.getKey() + token, "1", ttl, TimeUnit.MILLISECONDS);
            }
            
            LoginVO loginVO = new LoginVO();
            loginVO.setToken(newToken);
            
            log.info("用户Token刷新成功: userId={}, username={}", userId, username);
            return loginVO;
            
        } catch (Exception e) {
            log.error("Token刷新失败", e);
            throw new RuntimeException("Token刷新失败: " + e.getMessage());
        }
    }
}